package ray.surface;

import ray.Intersection;
import ray.Ray;
import ray.math.Point3;
import ray.math.Vector3;

public class Box extends Surface {
	
	/* The corner of the box with the smallest x, y, and z components. */
	protected final Point3 minPt = new Point3();
	public void setMinPt(Point3 minPt) { this.minPt.set(minPt); }

	/* The corner of the box with the largest x, y, and z components. */
	protected final Point3 maxPt = new Point3();
	public void setMaxPt(Point3 maxPt) { this.maxPt.set(maxPt); }

	public Box() { }

	/**
	 * @see Object#toString()
	 */
	public String toString() {
		
		return "box " + minPt + " " + maxPt + " " + shader + " end";
	}

	@Override
	public boolean intersect(Intersection inter, Ray ray) {
		

		double tmin, tmax, txmax, txmin, tymin, tymax, tzmin, tzmax;
		if (ray.direction.x >= 0) {
			txmin = (minPt.x - ray.origin.x) / ray.direction.x;
			txmax = (maxPt.x - ray.origin.x) / ray.direction.x;
		}
		else {
			txmin = (maxPt.x - ray.origin.x) / ray.direction.x;
			txmax = (minPt.x - ray.origin.x) / ray.direction.x;
		}
		if (ray.direction.y >= 0) {
			tymin = (minPt.y - ray.origin.y) / ray.direction.y;
			tymax = (maxPt.y - ray.origin.y) / ray.direction.y;
		}
		else {
			tymin = (maxPt.y - ray.origin.y) / ray.direction.y;
			tymax = (minPt.y - ray.origin.y) / ray.direction.y;
		}
		
		if ( (txmin > tymax) || (tymin > txmax) )
			return false;
		
		if (tymin > txmin) {
			tmin = tymin;
			inter.normal.set(0, ray.direction.y > 0 ? -1.0 : 1.0, 0);
		}
		else{
			tmin = txmin;
			inter.normal.set(ray.direction.x > 0 ? -1.0 : 1.0, 0, 0);
		}
		
		if (tymax < txmax)
			tmax = tymax;
		else{
			tmax = txmax;
		}
		
		if (ray.direction.z >= 0) {
			tzmin = (minPt.z - ray.origin.z) / ray.direction.z;
			tzmax = (maxPt.z - ray.origin.z) / ray.direction.z;
		}
		else {
			tzmin = (maxPt.z - ray.origin.z) / ray.direction.z;
			tzmax = (minPt.z - ray.origin.z) / ray.direction.z;
		}
		
		
		if ( (tmin > tzmax) || (tzmin > tmax) )
			return false;
		
		if (tzmin > tmin) {
			tmin = tzmin;
			inter.normal.set(0.0, 0.0, ray.direction.z > 0 ? -1.0 : 1.0);
		}
		//if (tzmax < tmax)
			//tmax = tzmax;
		
		if((tmin > ray.tEnd) || (tmin < ray.tStart))
			return false;
		
		
		//Point3 intersect = new Point3();
		//ray.getPoint(intersect, tmin);
		//inter.intersection.set(intersect);
		//inter.normal.set(getNormal(inter.intersection, ray));
		
		inter.intersection.set(ray.origin);
		inter.intersection.scaleAdd(tmin, ray.direction);
		inter.surface = this;
		if (inter.t > tmin){
			inter.t = tmin;
		}
		inter.normal.normalize();
		return true;
		}

public Vector3 getNormal(Point3 entryPoint, Ray ray) {
    Vector3 normal = new Vector3();
    if (Math.abs(entryPoint.x -  minPt.x) < ray.tEnd) {
        normal.x = -1;
    } else if (Math.abs(entryPoint.x - maxPt.x) < ray.tEnd) {
        normal.x = 1;
    } else if (Math.abs(entryPoint.y - minPt.y) < ray.tEnd) {
        normal.y = -1;
    } else if (Math.abs(entryPoint.y - maxPt.y) < ray.tEnd) {
        normal.y = 1;
    } else if (Math.abs(entryPoint.z - minPt.z) < ray.tEnd) {
        normal.z = -1;
    } else if (Math.abs(entryPoint.z - maxPt.z) < ray.tEnd) {
        normal.z = 1;
    }
    return normal;
	}
}